﻿// Gateway.Api 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Aurora.Redis;
using Microsoft.AspNetCore.Http;
using Aurora.AI.Domain.Domain;
using Microsoft.Extensions.Logging;
using Aurora.AI.Gateway.Models.Token;
using SqlSugar;
using Aurora.AI.Common.Helper;
using Aurora.AI.SqlSugar.Framework.Repositories;
using Mapster;

namespace Aurora.AI.Gateway.Services;

/// <summary>
/// token service
/// </summary>
public class TokenService(
    SettingService settingService,
    IRedisCache redisCache,
    UserAILimitService userAiLimitService,
    IRepository<Token> repository,
    ILogger<TokenService> logger)
{
    /// <summary>
    /// 根据 key 查找 token
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public async Task<Token?> FindByKey(string key)
    {
        return await repository.GetFirstAsync(x => x.Key.Equals(key) && !x.Disabled);
    }

    /// <summary>
    /// 检查token 是否有效
    /// 检查账号额度是否足够
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task<(Token? token, UserAILimit? userLimit)> CheckTokenAsync(HttpContext context)
    {
        var key = context.Request.Headers.Authorization.ToString().Replace("Bearer ", "").Trim();
        var requestQuota = await settingService.GetIntSetting("Setting:RequestQuota");
        if (requestQuota <= 0)
        {
            requestQuota = 5000;
        }

        UserAILimit? userLimit = null;
        Token? token = null;
        // su- 则是用户 token
        if (key.StartsWith("su-"))
        {
            // 查询用户 以及用户额度
            string userId = await redisCache.GetAsync<string>(key);
            if (string.IsNullOrEmpty(userId))
            {
                throw new UnauthorizedAccessException();
            }

            userLimit = await userAiLimitService.GetUserLimit(userId);
        }
        else
        {
            token = await FindByKey(key);
            if (token == null)
            {
                logger.LogWarning("Token 不存在");
                throw new UnauthorizedAccessException();
            }

            if (token.ExpiredTime < DateTimeOffset.Now)
            {
                logger.LogWarning("Token过期");
                throw new UnauthorizedAccessException();
            }

            if (token is { UnlimitedQuota: false } && token.RemainQuota < requestQuota)
            {
                logger.LogWarning("Token 额度不足");
                throw new ArgumentException("当前 Token 额度不足，请充值 Token 额度");
            }

            userLimit = await userAiLimitService.GetUserLimit(token.Creator);
        }

        if (userLimit == null)
        {
            logger.LogWarning("用户限制不存在");
            throw new UnauthorizedAccessException();
        }

        if (userLimit.ResidualCredit < requestQuota)
        {
            logger.LogWarning("用户额度不足");
            throw new ArgumentException("额度不足");
        }

        return (token, userLimit);
    }


    /// <summary>
    /// 获取分页列表
    /// </summary>
    /// <returns></returns>
    public async Task<(int total, List<TokenPageListResponse>)> GetPageListAsync(TokenPageListRequest request)
    {
        RefAsync<int> total = 0;
        List<TokenPageListResponse> result = new List<TokenPageListResponse>();
        var list = await repository.GetDb().Queryable<Token>()
            .WhereIF(!string.IsNullOrEmpty(request.Name), x => x.Name.Contains(request.Name))
            .WhereIF(!string.IsNullOrEmpty(request.Token), x => x.Key.Equals(request.Token))
            .ToOffsetPageAsync(request.Page, request.PageSize, total);
        if (list.Count == 0)
            return (total, result);
        result = list.Adapt<List<TokenPageListResponse>>();
        return (total, result);
    }


    public async Task<bool> CreateAsync(TokenCreateRequest request)
    {
        var entity = new Token()
        {
            CreationTime = DateTime.Now,
            ModificationTime = DateTime.Now,
            Modifier = request.OperatorId,
            Creator = request.OperatorId,
            RemainQuota = request.RemainQuota,
            UnlimitedQuota = request.UnlimitedQuota,
            ExpiredTime = request.ExpiredTime,
            UnlimitedExpired = request.UnlimitedExpired,
            Name = request.Name,
            IsDeleted = false
        };
        // 在这里需要生成key
        entity.Key = IdHelper.GenerateRandomString("sk-", 38);
        await repository.InsertAsync(entity);
        return true;
    }


    public async Task<bool> UpdateAsync(TokenUpdateRequest request)
    {
        var entity = await repository.GetByIdAsync(request.Id);
        if (entity == null)
        {
            throw new ArgumentException("未找到令牌");
        }

        entity.Name = request.Name;
        entity.ModificationTime = DateTime.Now;
        entity.Modifier = request.OperatorId;
        entity.RemainQuota = request.RemainQuota;
        entity.UnlimitedQuota = request.UnlimitedQuota;
        entity.ExpiredTime = request.ExpiredTime;
        entity.UnlimitedExpired = request.UnlimitedExpired;
        // entity.Key = request.Key;
        await repository.UpdateAsync(entity);
        return true;
    }


    public async Task<bool> UpdateDisable(TokenStatusUpdateRequest request)
    {
        var entity = await repository.GetByIdAsync(request.Id);
        if (entity == null)
        {
            throw new ArgumentException("未找到渠道");
        }

        entity.Disabled = request.Status;
        entity.ModificationTime = DateTime.Now;
        entity.Modifier = request.OperatorId;
        await repository.UpdateAsync(entity);
        return true;
    }

    public async Task<bool> RemoveAsync(string id)
    {
        return await repository.DeleteAsync(id);
    }
}